3
3
.
.
1
1
.
.
1
1
$
$
I
I
n
n
f
f
o
o
[
[
R
R
]
]
Dollar sign before the Variable name means a reference to a variable (and not the actual value).
You can use it to synch this Variable with the View's Property.
That we want to create two way binding between that Variable and that Property.
It is used in conjunction with the @State Property Wrapper which allows struct Property to be changed (because by
default struct and its Properties are immutable).
So that whenever User changes this Property this value should be automatically copied into that Variable.
And whenever we change that Variable (through the code) that value should be automatically copied into that Property.
You can think of dollar sign as giving a reference to a Variable so that SwiftUI can reference this Variable whenever View's
Property change in order to copy value from the View's Property into the Variable.
Content
Detailed Explanation
Example with @State
Single Variable
Multiple Variables
Multiple Variables in a struct
D
D
e
e
t
t
a
a
i
i
l
l
e
e
d
d
E
E
x
x
p
p
l
l
a
a
n
n
a
a
t
t
i
i
o
o
n
n
Some Views have Properties which can be changed by the User.
And this is the whole point of such Views - to allow user to SPECIFY some value by interacting with the View.
Example of such View would be a TextField.
Text Field has Property text and User can change it by typing inside the TextField.
But at the same time this Property can also be changed through the code.
When we add TextField View we can give a default value for text property.
And at any time during a program execution we can change it through the code.
In other words as the application is running both User and our Code can freely change this text Property.
In SwiftUI we can't directly access View's Properties during run time.
We can't get reference to TextField View in order to read its text Property in order to see which value User entered.
Instead we need to create a separate Variable which will server as a bridge between our code and View's Property.
So that when User changes View's Property SwiftUI automatically copies entered value into this Variable.
Now if our code wants to read the value of that Property it actually needs to read the Value of that Variable.
SwiftUI takes care that value of View's Property is always in synch with the value of this Variable.
Which means that this also works in the opposite direction.
If our code wants to change View's Property it can do that by changing value of that Variable.
And as we change the value of that Variable SwiftUI will immediately copy this value into Views' Property.
This way our change through the code is presented to the user by changing View's Property.
And this is the purpose of dollar sign. By placing dollar sign before the variable we are telling SwiftUI:
"Please synch this Variable with the View's Property.
Every tie this Variable changes please copy this value to the View's Property.
Every tie this View's Property changes please copy this value to the Variable."
Without the dollar sign we would be telling SwiftUI:
"Please use the current value of this Variable to set this View's Property."
If Variable later changes this will not change that View's Property.
If View's Property later changes, through User's interaction, this will not change that Variable.
In other words without dollar sign Variable and View's Property are not in synch.
And how do we tell SwiftUI to which View's Property to bind the Variable?
This is achieved by using this Variable at appropriate position when adding a View.
For instance to add TextView we need to write Text("Type here", text: $synchVariable).
In this call second parameter refers to text Property. So if we use our bridge Variable in that second place and with dollar
sign we are telling SwiftUI that we want to bind our bridge Variable to text Property.
SwiftUI actually forces us to use dollar sign before the variable for every Property that can be changed by the User.
We can't add TextField View by providing simple String as second parameter.
This results in error "Cannot convert value of type 'String' to expected argument type 'Binding<String>'".
Because as SwiftUI as second parameter expects us to give reference to a String Variable.
And at the same time we need to use @State for that variable because without that Variable can't be changed.
E
E
x
x
a
a
m
m
p
p
l
l
e
e
w
w
i
i
t
t
h
h
@
@
S
S
t
t
a
a
t
t
e
e
Double arrow indicates following
Changes made to TextField are automatically copied into name variable
Changes made to name variable are automatically copied into TextField
In other words
As you type into TextField, which changes its text Property, this value is automatically copied into name variable
But also when you change name variable, by pressing the button, new value is automatically copied into TextField
In this example we have a Text Field where Second Property holds text that is displayed or entered by the user.
Since we are interested in reading this Property we will define it through a @State Variable name.
Then we can read what text was entered by the User by reading this @State Variable name.
We will also use @State Variable name to set default value of that Property to "Please enter your name".
We are using @State variable because in SwiftUI you can't access Properties directly to read them or write to them.
We will also create a Button to demonstrate reading and writing to @State Variable name. When Button is pressed we
read the value of @State Variable name, which will contain entered text, and print it to Debug Console
change the value of @State Variable name to "Thank you for entering your name" which updates value of Text Field
Property and displays it to User
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var name = ""
var body: some View {
VStack {
TextField("Enter name", text: $name) //Update variable as you enter text
Text(name) //Read variable
Button("Button") { self.name = "Thank you" } //Update variable
}
}
}
Initial value Enter name & press Button Value is changed
Entered Name is printed in Debug Console
S
S
i
i
n
n
g
g
l
l
e
e
V
V
a
a
r
r
i
i
a
a
b
b
l
l
e
e
In this example we will bind a single Variable to View's Property.
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var userName : String = ""
var body:some View {
TextField("Enter User Name", text: $userName)
}
}
Output
M
M
u
u
l
l
t
t
i
i
p
p
l
l
e
e
V
V
a
a
r
r
i
i
a
a
b
b
l
l
e
e
s
s
In this example we will bind Multiple Variables to View's Properties.
ContentView.swift
import SwiftUI
struct ContentView: View {
@State var userName : String = ""
@State var password : String = ""
@State var emailAddress : String = ""
var body:some View {
VStack {
TextField("Enter Username" , text: $userName )
TextField("Enter Password" , text: $password )
TextField("Enter Email Address", text: $emailAddress)
}
}
}
Output
M
M
u
u
l
l
t
t
i
i
p
p
l
l
e
e
V
V
a
a
r
r
i
i
a
a
b
b
l
l
e
e
s
s
i
i
n
n
a
a
s
s
t
t
r
r
u
u
c
c
t
t
In this example we will bind Multiple Variables to View's Properties.
But these Variables will be inside a struct which allows us to more easily organize our data.
By using struct we only need to declare single @State Variable in our View as highlighted in yellow.
Instead of three separate Variables like in the previous example.
ContentView.swift
import SwiftUI
struct User {
var userName = "John"
var password = "123"
var emailAddress = "john@gmail.com"
}
struct ContentView: View {
@State var user = User(userName: "John", password: "123", emailAddress: "john@gmail.com")
var body:some View {
VStack {
TextField("Enter Username" , text: $user.userName )
TextField("Enter Password" , text: $user.password )
TextField("Enter Email Address", text: $user.emailAddress)
}
}
}
Output